﻿using LibGit2Sharp;
using NPOI.SS.Formula.Functions;
using System;
using System.Collections.Generic;
using System.Data;
using System.Data.Entity;
using System.IO;
using System.Linq;
using System.Text;
using System.Text.RegularExpressions;
using System.Threading.Tasks;
using static System.Windows.Forms.VisualStyles.VisualStyleElement.StartPanel;
using Match = System.Text.RegularExpressions.Match;

namespace FTP_progress
{
    class GitLab
    {
        /// <summary>
        /// 推送备份到git
        /// </summary>
        /// <param name="sourceFolderPath"></param>
        /// <param name="repoUrl"></param>
        /// <param name="repoPath"></param>
        /// <param name="userName"></param>
        /// <param name="pat"></param>
        /// <param name="logPath"></param>
        /// <param name="logFileName"></param>
        /// <param name="branchName"></param>
        public void PushFolderToGit(string sourceFolderPath, string repoUrl, string repoPath, string userName, string pat, string logPath, string logFileName, string deviceName, string branchName = "main")
        {
            string fileName = $"{logFileName}{DateTime.Now:yyyyMMddHHmmss}.txt";
            string filePath = Path.Combine(logPath, fileName);
            using (StreamWriter writer = new StreamWriter(filePath, false, Encoding.UTF8))
            {
                try
                {
                    // 确保本地仓库目录存在
                    if (!Directory.Exists(repoPath))
                    {
                        writer.WriteLine($"{deviceName}创建本地仓库目录: {repoPath}");
                        Console.WriteLine($"{deviceName}创建本地仓库目录: {repoPath}");
                        Directory.CreateDirectory(repoPath);
                    }
                    //++++++++++第一次运行需要初始化，而非clone

                    // ===== 1. 初始化或克隆仓库 =====   如果删除study文件夹就会把远程所有的文件复制过来！！！！
                    if (!Repository.IsValid(repoPath))
                    {
                        //如果是初始化本地仓库，默认分支是master,但gitlab仓库的默认分支是main
                        // 检查目录是否为空
                        //if (Directory.GetFiles(repoPath).Length == 0 && Directory.GetDirectories(repoPath).Length == 0)
                        //{
                        //    writer.WriteLine("Step1.1:初始化本地仓库...");
                        //    Console.WriteLine("Step1.1:初始化本地仓库...");

                        //    //  初始化本地Git仓库,并指定分支
                        //    Repository.Init(repoPath);


                        //    writer.WriteLine("Step1.2:添加远程仓库...");
                        //    Console.WriteLine("Step1.2:添加远程仓库...");


                        //    // 添加远程仓库
                        //    using (Repository repo = new Repository(repoPath))
                        //    {
                        //        // 添加远程仓库
                        //        repo.Network.Remotes.Add("origin", repoUrl);

                        //        // 配置用户信息
                        //        Configuration config = repo.Config;

                        //        config.Set("user.name", userName);
                        //        config.Set("user.email", $"{userName}@magna.com");
                        //    }

                        //    writer.WriteLine("Step1.3:克隆远程仓库...");
                        //    Console.WriteLine("Step1.3:克隆远程仓库...");

                        //    CloneOptions cloneOptions = new CloneOptions
                        //    {

                        //        BranchName = branchName,
                        //        Checkout = true,     // 克隆后是否检出文件，默认为 true
                        //        FetchOptions ={
                        //         // 设置 CredentialsProvider
                        //         CredentialsProvider = (url, usernameFromUrl, types) =>
                        //            new UsernamePasswordCredentials
                        //            {
                        //                Username = userName, // 替换为你的用户名
                        //                Password = pat // 替换为你的密码或PAT
                        //            },
                        //           // 如果需要，设置 CertificateCheck 回调（例如处理SSL证书问题）
                        //            CertificateCheck = (certificate, host, valid) =>
                        //            {
                        //                  return true; // 注意：在生产环境中应谨慎使用
                        //            }
                        //        }
                        //    };
                        //    Repository.Clone(repoUrl, repoPath, cloneOptions);
                        //}
                        //else
                        //{


                        //}

                        CloneOptions cloneOptions = new CloneOptions
                        {

                            BranchName = branchName,
                            Checkout = true,     // 克隆后是否检出文件，默认为 true
                            FetchOptions ={
                                 // 设置 CredentialsProvider
                                 CredentialsProvider = (url, usernameFromUrl, types) =>
                                    new UsernamePasswordCredentials
                                    {
                                        Username = userName, // 替换为你的用户名
                                        Password = pat // 替换为你的密码或PAT
                                    },
                                   // 如果需要，设置 CertificateCheck 回调（例如处理SSL证书问题）
                                    CertificateCheck = (certificate, host, valid) =>
                                    {
                                          return true; // 注意：在生产环境中应谨慎使用
                                    }
                                }
                        };
                        Repository.Clone(repoUrl, repoPath, cloneOptions);
                    }
                    else
                    {
                        writer.WriteLine($"{deviceName}：Step1:仓库已存在，无需初始化或克隆...");
                        Console.WriteLine($"{deviceName}:Step1:仓库已存在，无需初始化或克隆...");
                    }

                    // ===== 2. 复制整个文件夹到本地仓库 =====
                    string targetFolderPath = Path.Combine(repoPath, Path.GetFileName(sourceFolderPath));
                    // 删除目标文件夹（如果已存在）
                    if (Directory.Exists(targetFolderPath))
                    {
                        Directory.Delete(targetFolderPath, true);
                    }

                    // 复制整个文件夹
                    CopyDirectory(sourceFolderPath, targetFolderPath);
                    writer.WriteLine($"{deviceName}：Step2:已将文件夹复制到仓库: {targetFolderPath}");
                    Console.WriteLine($"{deviceName}：Step2:已将文件夹复制到仓库: {targetFolderPath}");


                    // ===== 3. Git 操作 =====
                    using (Repository repo = new Repository(repoPath))
                    {
                        // 拉取远程最新更改（避免冲突）
                        FetchRemoteChanges(repo, userName, pat);
                        // 递归添加所有文件:cite[1]
                        var allFiles = Directory.GetFiles(repoPath, "*.*", SearchOption.AllDirectories)
                            .Select(file => file.Substring(repoPath.Length + 1))
                            .Where(file => !file.StartsWith(".git")); // 排除.git文件夹

                        //暂存所有文件
                        foreach (var file in allFiles)
                        {
                            Commands.Stage(repo, file);
                        }
                        Commands.Stage(repo, "*");
                        Console.WriteLine($"{deviceName}：Step3:已暂存所有文件");

                        // 检查是否有更改需要提交
                        var status = repo.RetrieveStatus();

                        if (status.IsDirty)
                        {

                            // 提交更改
                            var author = new Signature(userName, $"{userName}@magna.com", DateTimeOffset.Now);

                            //提交信息                         
                            repo.Commit($"Add folder {Path.GetFileName(sourceFolderPath)} with all contents", author, author);

                            writer.WriteLine($"{deviceName}：Step3:提交更改完成");
                            Console.WriteLine($"{deviceName}：Step3:提交更改完成");
                        }
                        else
                        {
                            writer.WriteLine($"{deviceName}：Step3:没有需要提交的更改");
                            Console.WriteLine($"{deviceName}：Step3:没有需要提交的更改");

                            //插入没有修改记录
                            string sha = repo.Head.Tip.Id.Sha.Substring(0, 6);
                            Mysql emptySql = new Mysql("10.227.28.39", "db_bms", "hl", "hl");

                             Dictionary<string, object> emptyRecord = new Dictionary<string, object>
                             {
                                 ["RobotName"] = deviceName,
                                 ["Overview"] = "添加: 0, 修改: 0, 删除: 0, 重命名: 0",
                                 ["Added"] = "None",
                                 ["Modified"] = "None",
                                 ["Deleted"] = "None",
                                 ["Renamed"] = "None",
                                 ["SHA"] = repo.Head.Tip.Sha.Substring(0, 6), // 取前6位SHA
                                 ["remark"] = "",
                                 ["Status"] = "unchanged",
                                 ["Dtime"] = DateTime.Now
                                 // ["Dtime"] = DateTime.Now.ToString("yyyy-MM-dd HH:mm:ss")
                             };

                            emptySql.Insert("diff", emptyRecord);
                            return;
                        }

                        // ===== 4. 比较本地远程仓库差异 =====

                        //将差异保存到数据库
                        try
                        {
                            // 创建Git差异服务实例
                            CMP gitDiffService = new CMP(repoPath, userName, pat);

                            // 获取本地与远程的差异
                            var diffs = gitDiffService.GetLocalRemoteDiff(branchName);

                            // 保存差异信息到文件
                            gitDiffService.SaveDiffToFile(diffs, writer, branchName);

                            writer.WriteLine($"{deviceName}：Step4:比较文件差异完成！");
                            Console.WriteLine($"{deviceName}：Step4:比较文件差异完成！");

                        }
                        catch (Exception ex)
                        {
                            writer.WriteLine($"{deviceName}：Step4:比较文件差异时,发生错误: {ex.Message}");
                            Console.WriteLine($"{deviceName}：Step4:比较文件差异时,发生错误: {ex.Message}");
                        }

                        ///////////////////////////////////////////////将差异保存到sqlite数据库////////////////////////////////////////
                        // 初始化差异记录器
                        // GitDiffRecorderSqlite diffRecorderSqlite = new GitDiffRecorderSqlite(repo, deviceName);
                        // 记录差异到数据库
                        //  diffRecorderSqlite.RecordDiffToDatabase(branchName);

                        ///////////////////////////////////////////////将差异保存到mysql数据库////////////////////////////////////////
                        // 初始化差异记录器
                        GitDiffRecorderMysql diffRecorderMysql = new GitDiffRecorderMysql(repo, deviceName);
                        // 记录差异到数据库
                        diffRecorderMysql.RecordDiffToDatabase(branchName);

                        // ===== 5. 推送到远程仓库 =====
                        SafePushWithFallback(repo, userName, pat, writer);
                    }
                }
                catch (Exception ex)
                {
                    writer.WriteLine($"{deviceName}：推送到git错误: {ex.Message}");
                    Console.WriteLine($"{deviceName}：推送到git错误: {ex.Message}");
                    // Console.WriteLine($"详细信息: {ex.InnerException?.Message}");
                }
            }
        }

        /// <summary>
        /// 强制推送到gitlab
        /// </summary>
        /// <param name="repo"></param>
        /// <param name="userName"></param>
        /// <param name="pat"></param>
        /// <param name="writer"></param>
        /// <returns></returns>
        public bool SafePushWithFallback(Repository repo, string userName, string pat, TextWriter writer = null)
        {
            var remote = repo.Network.Remotes["origin"];
            var branch = repo.Head;

            // 设置上游跟踪分支（如果尚未设置）:cite[4]
            if (!branch.IsTracking)
            {
                repo.Branches.Update(branch,
                    b => b.Remote = remote.Name,
                    b => b.UpstreamBranch = branch.CanonicalName);
            }

            PushOptions pushOptions = new PushOptions
            {
                CredentialsProvider = (url, user, cred) =>
                    new UsernamePasswordCredentials { Username = userName, Password = pat }
            };

            try
            {
                // 首先尝试常规推送
                repo.Network.Push(branch, pushOptions);

                writer?.WriteLine("成功推送到远程仓库！");
                Console.WriteLine("成功推送到远程仓库！");
                return true;
            }
            catch (NonFastForwardException)
            {
                // 处理非快进错误:cite[9]
                writer?.WriteLine("警告: 无法快进推送，正在尝试强制推送...");
                Console.WriteLine("警告: 无法快进推送，正在尝试强制推送...");

                try
                {
                    // 强制推送:cite[9]
                    string forcePushRefSpec = "+" + branch.CanonicalName;
                    repo.Network.Push(remote, forcePushRefSpec, pushOptions);

                    writer?.WriteLine("强制推送成功完成！");
                    Console.WriteLine("强制推送成功完成！");
                    return true;
                }
                catch (Exception forceEx)
                {
                    writer?.WriteLine($"强制推送失败: {forceEx.Message}");
                    Console.WriteLine($"强制推送失败: {forceEx.Message}");
                    return false;
                }
            }
            catch (Exception ex)
            {
                writer?.WriteLine($"推送失败: {ex.Message}");
                Console.WriteLine($"推送失败: {ex.Message}");
                return false;
            }
        }

        /// <summary>
        /// 文件夹拷贝
        /// </summary>
        /// <param name="sourceDir"></param>
        /// <param name="targetDir"></param>
        private static void CopyDirectory(string sourceDir, string targetDir)
        {
            try
            {
                // 创建目标目录
                Directory.CreateDirectory(targetDir);
                Console.WriteLine($"创建目录: {targetDir}");

                // 复制所有文件
                foreach (var file in Directory.GetFiles(sourceDir))
                {
                    try
                    {
                        string destFile = Path.Combine(targetDir, Path.GetFileName(file));
                        File.Copy(file, destFile, true);
                        Console.WriteLine($"复制文件: {file} -> {destFile}");
                    }
                    catch (Exception ex)
                    {
                        Console.WriteLine($"复制文件失败 {file}: {ex.Message}");
                    }
                }
                // 递归复制所有子目录
                foreach (var directory in Directory.GetDirectories(sourceDir))
                {
                    try
                    {
                        string dirName = Path.GetFileName(directory);
                        string destDir = Path.Combine(targetDir, dirName);
                        CopyDirectory(directory, destDir);
                    }
                    catch (Exception ex)
                    {
                        Console.WriteLine($"处理子目录失败 {directory}: {ex.Message}");
                    }
                }
            }
            catch (Exception ex)
            {
                Console.WriteLine($"复制目录失败 {sourceDir} -> {targetDir}: {ex.Message}");
            }
        }

        /// <summary>
        /// 获取远程最新更改
        /// </summary>
        private static void FetchRemoteChanges(Repository repo, string username, string pat)
        {
            try
            {
                var remote = repo.Network.Remotes["origin"];
                if (remote == null) return;

                var fetchOptions = new FetchOptions
                {
                    CredentialsProvider = (url, user, cred) =>
                        new UsernamePasswordCredentials { Username = username, Password = pat }
                };

                var refSpecs = remote.FetchRefSpecs.Select(x => x.Specification);
                Commands.Fetch(repo, remote.Name, refSpecs, fetchOptions, null);
                Console.WriteLine("已获取远程最新更改");
            }
            catch (Exception ex)
            {
                Console.WriteLine($"获取远程更改时警告: {ex.Message}");
            }
        }
    }
    /// <summary>
    /// 比较
    /// </summary>
    public class CMP
    {
        public Repository Repository { get; private set; }
        public string RepoPath { get; }
        private string userName;
        private string passWord;
        public CMP(string repoPath, string userName, string passWord)
        {
            RepoPath = repoPath;
            if (!Repository.IsValid(repoPath))
            {
                throw new ArgumentException("无效的Git仓库路径");
            }
            Repository = new Repository(repoPath);
            this.userName = userName;
            this.passWord = passWord;
        }

        public IEnumerable<FileDiff> GetLocalRemoteDiff(string branchName = "main")
        {
            // 确保远程分支是最新的
            FetchRemoteChanges();

            // 获取远程分支
            var remoteBranch = GetRemoteBranch(branchName);
            if (remoteBranch == null)
            {
                throw new Exception($"找不到远程分支: origin/{branchName}");
            }

            // 获取本地分支
            var localBranch = GetLocalBranch(branchName);
            if (localBranch == null)
            {
                throw new Exception($"找不到本地分支: {branchName}");
            }

            // 比较差异
            var changes = Repository.Diff.Compare<TreeChanges>(remoteBranch.Tip.Tree, localBranch.Tip.Tree);

            var result = new List<FileDiff>();
            foreach (var change in changes)
            {
                var patch = Repository.Diff.Compare<Patch>(remoteBranch.Tip.Tree, localBranch.Tip.Tree, new[] { change.Path });
                result.Add(new FileDiff
                {
                    Path = change.Path,
                    Status = change.Status,
                    Patch = patch?.Content
                });
            }
            return result;
        }

        private string GetFileContentFromTree(Tree tree, string path)
        {
            try
            {
                var treeEntry = tree[path];
                if (treeEntry != null && treeEntry.Target is Blob blob)
                {
                    using (var contentStream = blob.GetContentStream())
                    using (var reader = new StreamReader(contentStream))
                    {
                        return reader.ReadToEnd();
                    }
                }
            }
            catch (Exception ex)
            {
                // 记录错误或处理异常
                Console.WriteLine($"无法获取文件内容: {path}, 错误: {ex.Message}");
            }
            return string.Empty;
        }

        // 辅助方法：生成删除文件的补丁
        private string GenerateDeletePatch(string path, string content)
        {
            if (string.IsNullOrEmpty(content))
            {
                return $"--- a/{path}\n+++ /dev/null\n@@ -1 +0,0 @@";
            }

            // 计算行数
            int lineCount = content.Split('\n').Length;

            // 生成补丁
            var patch = new StringBuilder();
            patch.AppendLine($"--- a/{path}");
            patch.AppendLine("+++ /dev/null");
            patch.AppendLine($"@@ -1,{lineCount} +0,0 @@");

            // 添加内容行，每行前面加上减号
            foreach (var line in content.Split('\n'))
            {
                patch.AppendLine($"-{line}");
            }

            return patch.ToString();
        }


        public string SaveDiffToFile(IEnumerable<FileDiff> fileDiffs, string branchName = "main")
        {
            var sb = new StringBuilder();

            // 写入文件头部信息
            sb.AppendLine($"本地与远程仓库差异比较报告");
            sb.AppendLine($"生成时间: {DateTime.Now:yyyy-MM-dd HH:mm:ss}");
            sb.AppendLine($"仓库路径: {RepoPath}");
            sb.AppendLine($"比较分支: 本地 {branchName} vs 远程 origin/{branchName}");
            sb.AppendLine("==============================================");
            sb.AppendLine();

            // 写入差异概览
            sb.AppendLine($"差异文件总数: {fileDiffs.Count()}");
            sb.AppendLine("----------------------------------------------");

            int added = fileDiffs.Count(f => f.Status == ChangeKind.Added);
            int modified = fileDiffs.Count(f => f.Status == ChangeKind.Modified);
            int deleted = fileDiffs.Count(f => f.Status == ChangeKind.Deleted);
            int renamed = fileDiffs.Count(f => f.Status == ChangeKind.Renamed);

            sb.AppendLine($"新增文件: {added}");
            sb.AppendLine($"修改文件: {modified}");
            sb.AppendLine($"删除文件: {deleted}");
            sb.AppendLine($"重命名文件: {renamed}");
            sb.AppendLine();
            sb.AppendLine("==============================================");
            sb.AppendLine();

            // 写入每个文件的详细差异
            foreach (var fileDiff in fileDiffs)
            {
                // 解码文件路径
                string decodedPath = GitDiffDecoder.DecodeGitOctalEscape(fileDiff.Path);//文件路径

                //string decodedPatch = GitDiffDecoder.ParseAndFormatDiff(GitDiffDecoder.DecodeGitOctalEscape(fileDiff.Patch ?? ""));//文件差异

                string decodedPatch = GitDiffDecoder.ParseAndFormatDiff(fileDiff.Patch);//文件差异


                sb.AppendLine($"{fileDiff.StatusSymbol} {fileDiff.Path} ({fileDiff.StatusText})");
                sb.AppendLine("----------------------------------------------");

                if (!string.IsNullOrWhiteSpace(decodedPatch))
                {
                    sb.AppendLine(decodedPatch);
                }
                else
                {
                    sb.AppendLine($"无详细差异内容 ({fileDiff.StatusText}操作)");
                }

                sb.AppendLine();
                sb.AppendLine("----------------------------------------------");
                sb.AppendLine();
            }

            // 写入汇总信息
            sb.AppendLine("==============================================");
            sb.AppendLine("比较完成");

            return sb.ToString();
        }


        public void SaveDiffToFile(IEnumerable<FileDiff> fileDiffs, StreamWriter writer, string branchName = "main")
        {
            string diffReport = SaveDiffToFile(fileDiffs, branchName);
            writer.Write(diffReport);
        }




        private Branch GetLocalBranch(string branchName)
        {
            return Repository.Branches.FirstOrDefault(b =>
                b.FriendlyName.Equals(branchName, StringComparison.OrdinalIgnoreCase));
        }



        private Branch GetRemoteBranch(string branchName)
        {
            return Repository.Branches.FirstOrDefault(b =>
                b.IsRemote &&
                b.FriendlyName.Equals($"origin/{branchName}", StringComparison.OrdinalIgnoreCase));
        }

        private void FetchRemoteChanges()
        {
            var remote = Repository.Network.Remotes["origin"];
            if (remote == null) return;

            var refSpecs = remote.FetchRefSpecs.Select(x => x.Specification);

            var fetchOptions = new FetchOptions
            {
                CredentialsProvider = (url, usernameFromUrl, types) =>
                    new UsernamePasswordCredentials
                    {
                        Username = userName,
                        Password = passWord
                    }
            };
            Commands.Fetch(Repository, remote.Name, refSpecs, fetchOptions, null);
        }
    }

    public class FileDiff
    {
        public string Path { get; set; }
        public ChangeKind Status { get; set; }
        public string Patch { get; set; }

        public string StatusSymbol
        {
            get
            {
                switch (Status)
                {
                    case ChangeKind.Added:
                        return "[+]";
                    case ChangeKind.Deleted:
                        return "[-]";
                    case ChangeKind.Modified:
                        return "[M]";
                    case ChangeKind.Renamed:
                        return "[R]";
                    default:
                        return "[?]";
                }
            }
        }

        public string StatusText
        {
            get
            {
                switch (Status)
                {
                    case ChangeKind.Added:
                        return "添加";
                    case ChangeKind.Deleted:
                        return "删除";
                    case ChangeKind.Modified:
                        return "修改";
                    case ChangeKind.Renamed:
                        return "重命名";
                    default:
                        return "未知";
                }
            }
        }

    }
    /// <summary>
    /// 解码
    /// </summary>
    public class GitDiffDecoder
    {
        /// <summary>
        /// 将Git的八进制转义序列解码为UTF-8字符串
        /// </summary>
        public static string DecodeGitOctalEscape(string input)
        {
            if (string.IsNullOrEmpty(input))
                return input;

            // 匹配所有八进制转义序列
            var regex = new Regex(@"\\([0-7]{3})");
            var matches = regex.Matches(input);

            // 如果没有找到转义序列，直接返回原始字符串
            if (matches.Count == 0)
                return input;

            // 创建一个字节列表来存储解码后的字节
            List<byte> byteList = new List<byte>();
            int lastIndex = 0;

            // 处理所有匹配的转义序列
            foreach (Match match in matches)
            {
                // 添加匹配前的普通文本
                if (match.Index > lastIndex)
                {
                    string normalText = input.Substring(lastIndex, match.Index - lastIndex);
                    byteList.AddRange(Encoding.UTF8.GetBytes(normalText));
                }

                // 处理八进制转义序列
                string octalStr = match.Groups[1].Value;
                byte byteValue = Convert.ToByte(octalStr, 8);
                byteList.Add(byteValue);

                lastIndex = match.Index + match.Length;
            }

            // 添加最后一个匹配后的普通文本
            if (lastIndex < input.Length)
            {
                string remainingText = input.Substring(lastIndex);
                byteList.AddRange(Encoding.UTF8.GetBytes(remainingText));
            }

            // 将字节数组转换为UTF-8字符串
            return Encoding.UTF8.GetString(byteList.ToArray());
        }

        /// <summary>
        /// 处理Git差异输出中的文件名
        /// </summary>
        public static string ProcessGitDiffFileName(string gitDiffOutput)
        {
            // 提取文件名部分（在"a/"和"b/"之后的内容）
            var match = Regex.Match(gitDiffOutput, @"[ab]/(.+)");
            if (match.Success)
            {
                string encodedFileName = match.Groups[1].Value;
                return DecodeGitOctalEscape(encodedFileName);
            }

            return gitDiffOutput;
        }

        /// <summary>
        /// 解析 Git diff 输出并转换为易读格式
        /// </summary>
        /// <param name="diffOutput">Git diff 原始输出</param>
        /// <returns>格式化后的差异信息</returns>
        public static string ParseAndFormatDiff(string diffOutput)
        {
            if (string.IsNullOrEmpty(diffOutput))
                return "无差异信息";

            StringBuilder result = new StringBuilder();
            string[] lines = diffOutput.Split('\n');

            // 解析文件头信息
            if (lines.Length > 0 && lines[0].StartsWith("diff --git"))
            {
                // 提取文件名
                Match fileMatch = Regex.Match(lines[0], @"diff --git ""a/(.+)"" ""b/(.+)""");
                if (fileMatch.Success)
                {
                    string oldFile = DecodeGitOctalEscape(fileMatch.Groups[1].Value);
                    string newFile = DecodeGitOctalEscape(fileMatch.Groups[2].Value);

                    result.AppendLine($"文件: {oldFile} → {newFile}");
                    result.AppendLine();
                }
            }

            // 解析变更块
            for (int i = 0; i < lines.Length; i++)
            {
                string line = lines[i];

                // 处理变更块头部
                if (line.StartsWith("@@ "))
                {
                    Match hunkMatch = Regex.Match(line, @"@@ -(\d+),(\d+) \+(\d+),(\d+) @@");
                    if (hunkMatch.Success)
                    {
                        int oldStart = int.Parse(hunkMatch.Groups[1].Value);
                        int oldLineCount = int.Parse(hunkMatch.Groups[2].Value);
                        int newStart = int.Parse(hunkMatch.Groups[3].Value);
                        int newLineCount = int.Parse(hunkMatch.Groups[4].Value);

                        result.AppendLine($"变更位置: 第{oldStart}行 (共{oldLineCount}行) → 第{newStart}行 (共{newLineCount}行)");
                        result.AppendLine();

                        // 处理变更内容
                        for (int j = i + 1; j < lines.Length; j++)
                        {
                            string contentLine = lines[j];

                            // 如果遇到新的变更块或文件头，停止处理
                            if (contentLine.StartsWith("@@ ") || contentLine.StartsWith("diff --git"))
                                break;

                            // 跳过文件头行
                            if (contentLine.StartsWith("--- ") || contentLine.StartsWith("+++ ") ||
                                contentLine.StartsWith("index "))
                                continue;

                            // 处理内容行
                            if (contentLine.StartsWith("-"))
                            {
                                result.AppendLine($"[删除] {contentLine.Substring(1)}");
                            }
                            else if (contentLine.StartsWith("+"))
                            {
                                result.AppendLine($"[添加] {contentLine.Substring(1)}");
                            }
                            else if (contentLine.StartsWith("\\"))
                            {
                                // 处理特殊标记
                                if (contentLine.Contains("No newline at end of file"))
                                {
                                    result.AppendLine("[提示] 文件末尾没有换行符");
                                }
                            }
                            else
                            {
                                result.AppendLine($"[不变] {contentLine}");
                            }
                        }

                        result.AppendLine();
                        result.AppendLine("=".PadRight(50, '='));
                        result.AppendLine();
                    }
                }
            }

            return result.ToString();
        }

    }

    /// <summary>
    /// 差异数据记录
    /// </summary>
    public class GitDiffRecorderSqlite
    {
        private readonly Sqlite _database;
        private readonly Repository _repository;
        private readonly string _robotName;

        public GitDiffRecorderSqlite(Repository repo, string robotName)
        {
            _database = new Sqlite();
            _repository = repo;
            _robotName = robotName;
        }

        /// <summary>
        /// 比较本地和远程差异并记录到数据库
        /// </summary>
        /// <param name="branchName">分支名称</param>
        public void RecordDiffToDatabase(string branchName = "main")
        {
            try
            {
                // 获取差异信息
                var fileDiffs = GetLocalRemoteDiff(branchName);

                // 统计各类变更数量
                var overview = CalculateOverview(fileDiffs);

                // 准备数据库记录
                var diffRecord = new Dictionary<string, object>
                {
                    ["RobotName"] = _robotName,
                    ["Overview"] = overview,
                    ["Added"] = GetFileContentsByStatus(fileDiffs, ChangeKind.Added),
                    ["Modified"] = GetFileContentsByStatus(fileDiffs, ChangeKind.Modified),
                    ["Deleted"] = GetFileContentsByStatus(fileDiffs, ChangeKind.Deleted),
                    ["Renamed"] = GetFileContentsByStatus(fileDiffs, ChangeKind.Renamed),
                    ["SHA"] = _repository.Head.Tip.Sha.Substring(0, 6), // 取前6位SHA
                    ["remark"] = "",
                    ["Status"] = "changed",
                    ["Dtime"] = DateTime.Now
                    // ["Dtime"] = DateTime.Now.ToString("yyyy-MM-dd HH:mm:ss")

                };

                // 插入数据库
                _database.Insert("diff", diffRecord);

                Console.WriteLine($"{_robotName}：成功记录差异到SQLite数据库，共 {fileDiffs.Count()} 个文件变更");
            }
            catch (Exception ex)
            {
                Console.WriteLine($"{_robotName}：记录差异到SQLite数据库时出错: {ex.Message}");
                throw;
            }
        }

        /// <summary>
        /// 获取本地和远程差异
        /// </summary>
        private IEnumerable<FileDiff> GetLocalRemoteDiff(string branchName = "main")
        {
            // 确保远程分支是最新的该处有点错误！！！！！！！！！！！！！！！！

            // FetchRemoteChanges();

            // 获取远程分支
            var remoteBranch = GetRemoteBranch(branchName);
            if (remoteBranch == null)
            {
                throw new Exception($"找不到远程分支: origin/{branchName}");
            }

            // 获取本地分支
            var localBranch = GetLocalBranch(branchName);
            if (localBranch == null)
            {
                throw new Exception($"找不到本地分支: {branchName}");
            }

            // 比较差异
            var changes = _repository.Diff.Compare<TreeChanges>(remoteBranch.Tip.Tree, localBranch.Tip.Tree);

            var result = new List<FileDiff>();
            foreach (var change in changes)
            {
                var patch = _repository.Diff.Compare<Patch>(remoteBranch.Tip.Tree, localBranch.Tip.Tree, new[] { change.Path });
                result.Add(new FileDiff
                {
                    Path = change.Path,
                    Status = change.Status,
                    Patch = patch?.Content
                });
            }
            return result;
        }

        /// <summary>
        /// 统计各类变更数量
        /// </summary>
        private string CalculateOverview(IEnumerable<FileDiff> fileDiffs)
        {
            var addCount = fileDiffs.Count(f => f.Status == ChangeKind.Added);
            var modifyCount = fileDiffs.Count(f => f.Status == ChangeKind.Modified);
            var deleteCount = fileDiffs.Count(f => f.Status == ChangeKind.Deleted);
            var renameCount = fileDiffs.Count(f => f.Status == ChangeKind.Renamed);

            return $"添加: {addCount}, 修改: {modifyCount}, 删除: {deleteCount}, 重命名: {renameCount}";
        }

        /// <summary>
        /// 根据变更类型获取文件内容
        /// </summary>
        private string GetFileContentsByStatus(IEnumerable<FileDiff> fileDiffs, ChangeKind status)
        {
            var files = fileDiffs.Where(f => f.Status == status).ToList();
            if (!files.Any()) return string.Empty;

            var contents = new List<string>();
            foreach (var file in files)
            {
                string a = GitDiffDecoder.DecodeGitOctalEscape(file.Path);
                string b = GitDiffDecoder.ParseAndFormatDiff(file.Patch);
                string content = GitDiffDecoder.DecodeGitOctalEscape(file.Path) + GitDiffDecoder.ParseAndFormatDiff(file.Patch);
                contents.Add(content);
            }
            string result = string.Join(Environment.NewLine + "---" + Environment.NewLine, contents);
            return result;
        }

        /// <summary>
        /// 获取远程分支
        /// </summary>
        private Branch GetRemoteBranch(string branchName)
        {
            return _repository.Branches[$"origin/{branchName}"];
        }

        /// <summary>
        /// 获取本地分支
        /// </summary>
        private Branch GetLocalBranch(string branchName)
        {
            return _repository.Branches[branchName];
        }

        /// <summary>
        /// 获取远程变更
        /// </summary>

        private void FetchRemoteChanges(string userName, string passWord)
        {
            var remote = _repository.Network.Remotes["origin"];
            if (remote == null) return;

            var refSpecs = remote.FetchRefSpecs.Select(x => x.Specification);

            var fetchOptions = new FetchOptions
            {
                CredentialsProvider = (url, usernameFromUrl, types) =>
                    new UsernamePasswordCredentials
                    {
                        Username = userName,
                        Password = passWord
                    }
            };
            Commands.Fetch(_repository, remote.Name, refSpecs, fetchOptions, "正在获取远程变更...");
        }

    }

    public class GitDiffRecorderMysql
    {
        private readonly Mysql _database;
        private readonly Repository _repository;
        private readonly string _robotName;

        public GitDiffRecorderMysql(Repository repo, string robotName)
        {
            _database = new Mysql("10.227.28.39", "db_bms", "hl", "hl");
            _repository = repo;
            _robotName = robotName;
        }

        /// <summary>
        /// 比较本地和远程差异并记录到数据库
        /// </summary>
        /// <param name="branchName">分支名称</param>
        public void RecordDiffToDatabase(string branchName = "main")
        {
            try
            {
                // 获取差异信息
                var fileDiffs = GetLocalRemoteDiff(branchName);

                // 统计各类变更数量
                var overview = CalculateOverview(fileDiffs);

                // 准备数据库记录
                var diffRecord = new Dictionary<string, object>
                {
                    ["RobotName"] = _robotName,
                    ["Overview"] = overview,
                    ["Added"] = GetFileContentsByStatus(fileDiffs, ChangeKind.Added),
                    ["Modified"] = GetFileContentsByStatus(fileDiffs, ChangeKind.Modified),
                    ["Deleted"] = GetFileContentsByStatus(fileDiffs, ChangeKind.Deleted),
                    ["Renamed"] = GetFileContentsByStatus(fileDiffs, ChangeKind.Renamed),
                    ["SHA"] = _repository.Head.Tip.Sha.Substring(0, 6), // 取前6位SHA
                    ["remark"] = "",
                    ["Status"] = "changed",
                    ["Dtime"] = DateTime.Now
                    // ["Dtime"] = DateTime.Now.ToString("yyyy-MM-dd HH:mm:ss")

                };

                // 插入数据库
                _database.Insert("diff", diffRecord);

                Console.WriteLine($"{_robotName}成功记录差异到MySQL数据库，共 {fileDiffs.Count()} 个文件变更");
            }
            catch (Exception ex)
            {
                Console.WriteLine($"{_robotName}记录差异到MySQL数据库时出错: {ex.Message}");
                throw;
            }
        }

        /// <summary>
        /// 获取本地和远程差异
        /// </summary>
        private IEnumerable<FileDiff> GetLocalRemoteDiff(string branchName = "main")
        {
            // 确保远程分支是最新的
            //  FetchRemoteChanges();

            // 获取远程分支
            var remoteBranch = GetRemoteBranch(branchName);
            if (remoteBranch == null)
            {
                throw new Exception($"找不到远程分支: origin/{branchName}");
            }

            // 获取本地分支
            var localBranch = GetLocalBranch(branchName);
            if (localBranch == null)
            {
                throw new Exception($"找不到本地分支: {branchName}");
            }

            // 比较差异
            var changes = _repository.Diff.Compare<TreeChanges>(remoteBranch.Tip.Tree, localBranch.Tip.Tree);

            var result = new List<FileDiff>();
            foreach (var change in changes)
            {
                var patch = _repository.Diff.Compare<Patch>(remoteBranch.Tip.Tree, localBranch.Tip.Tree, new[] { change.Path });
                result.Add(new FileDiff
                {
                    Path = change.Path,
                    Status = change.Status,
                    Patch = patch?.Content
                });
            }
            return result;
        }

        /// <summary>
        /// 统计各类变更数量
        /// </summary>
        private string CalculateOverview(IEnumerable<FileDiff> fileDiffs)
        {
            var addCount = fileDiffs.Count(f => f.Status == ChangeKind.Added);
            var modifyCount = fileDiffs.Count(f => f.Status == ChangeKind.Modified);
            var deleteCount = fileDiffs.Count(f => f.Status == ChangeKind.Deleted);
            var renameCount = fileDiffs.Count(f => f.Status == ChangeKind.Renamed);

            return $"添加: {addCount}, 修改: {modifyCount}, 删除: {deleteCount}, 重命名: {renameCount}";
        }

        /// <summary>
        /// 根据变更类型获取文件内容
        /// </summary>
        private string GetFileContentsByStatus(IEnumerable<FileDiff> fileDiffs, ChangeKind status)
        {
            var files = fileDiffs.Where(f => f.Status == status).ToList();
            if (!files.Any()) return string.Empty;

            var contents = new List<string>();
            foreach (var file in files)
            {
                // GitDiffDecoder.ParseAndFormatDiff
                //  var content1 = $"{file.Path}: {file.Patch}";
                //string content = file.Path + GitDiffDecoder.ParseAndFormatDiff(GitDiffDecoder.DecodeGitOctalEscape(file.Patch));


                string a = GitDiffDecoder.DecodeGitOctalEscape(file.Path);
                string b = GitDiffDecoder.ParseAndFormatDiff(file.Patch);
                string content = GitDiffDecoder.DecodeGitOctalEscape(file.Path) + GitDiffDecoder.ParseAndFormatDiff(file.Patch);
                contents.Add(content);
            }
            string result = string.Join(Environment.NewLine + "---" + Environment.NewLine, contents);

            return result;
        }

        /// <summary>
        /// 获取远程分支
        /// </summary>
        private Branch GetRemoteBranch(string branchName)
        {
            return _repository.Branches[$"origin/{branchName}"];
        }

        /// <summary>
        /// 获取本地分支
        /// </summary>
        private Branch GetLocalBranch(string branchName)
        {
            return _repository.Branches[branchName];
        }

        /// <summary>
        /// 获取远程变更
        /// </summary>
        private void FetchRemoteChanges()
        {
            try
            {
                var remote = _repository.Network.Remotes["origin"];
                var refSpecs = remote.FetchRefSpecs.Select(x => x.Specification);
                Commands.Fetch(_repository, remote.Name, refSpecs, null, "正在获取远程变更...");
            }
            catch (Exception ex)
            {
                Console.WriteLine($"获取远程变更时出错: {ex.Message}");
            }
        }
    }


}
